#include "SocketIO.h"

using std::cout;
using std::endl;

SocketIO::SocketIO(int fd) : _fd{fd} {}

int SocketIO::readn(char *buf, size_t n)
{
    int left = n;
    char *ptr = buf;
    int ret = 0;
    while (left > 0)
    {
        ret = read(_fd, ptr, left);
        if (ret == -1 && errno == EINTR)
        {
            continue;
        }
        else if (ret == -1)
        {
            perror("readn error");
            return n - left;
        }
        else
        {
            left -= ret;
        }
    }
    return n - left;
}

int SocketIO::readLine(char *buf, size_t n)
{
    int left = n;
    char *ptr = buf;
    int ret{}, total{};
    while (left > 0)
    {
        // 并不会清除内核读缓冲区内的数据
        ret = recv(_fd, ptr, left, MSG_PEEK);
        if (ret == -1 && errno == EINTR)
        {
            continue;
        }
        else if (ret == -1)
        {
            perror("readLine is error");
            return n - left;
        }
        else if (ret == 0)
        {
            return ret;
        }

        for (int idx{}; idx < ret; idx++)
        {
            if (ptr[idx] == '\n')
            {
                readn(ptr, idx + 1);
                ptr += idx + 1;
                *ptr = '\0';

                return total + idx + 1;
            }
        }
        readn(ptr, ret);
        ptr += ret;
        total += ret;
        left -= ret;
    }
    *ptr = '\0';
    return n - left;
}

int SocketIO::writen(std::string str, size_t n)
{
    int left = n;
    const char *ptr = str.c_str();
    int ret{};
    while (left > 0)
    {
        ret = ::send(_fd, ptr, left, 0);
        if (ret == -1 && errno == EINTR)
        {
            continue;
        }
        else if (ret == -1)
        {
            perror("writen");
            return n - left;
        }
        else
        {
            left -= ret;
            ptr += ret;
        }
    }
    return strlen(ptr);
}
